<?php
/*
 * @Description    : 短信发送任务
 * @Version        : 1.0.0
 * @Author         : QianLong
 * @Date           : 2020-01-22 15:56:35
 * @LastEditors    : QianLong
 * @LastEditTime   : 2024-02-06 11:22:03
 */

declare(strict_types=1);

namespace App\Job;

use Hyperf\AsyncQueue\Job;

class SmsSendJob extends Job
{
    public $params;
    public $redisCache;

    public function __construct($params, $redisCache)
    {
        $this->params = $params;
        $this->redisCache = $redisCache;
    }

    public function handle()
    {
        if (!empty($this->params) && is_array($this->params)) {
            $serverInfo = $this->redisCache->getSmsServer($this->params['ss_id']);
            $smsSetting = $this->redisCache->getSmsSetting($this->params['uid']);
            if (isset($serverInfo['ak_from']) && $serverInfo['ak_from'] == 'platform' && isset($serverInfo['ak_id']) && !empty($serverInfo['ak_id'])) {
                $akInfo = $this->redisCache->getAk($serverInfo['ak_id'], $this->params['uid']);
                unset($akInfo['_id']);
                $serverInfo = array_merge($serverInfo, $akInfo);
                unset($akInfo);
            }

            \Hyperf\Retry\Retry::whenReturns(false) // 当返回false时重试
                ->max(2) // 最多5次
                ->inSeconds(30 * 60) // 最长30*60秒
                ->sleep(15 * 1000) // 间隔30秒
                ->fallback(function () use ($smsSetting, $serverInfo) {
                    return $this->doSend($smsSetting, $serverInfo);
                }) // fallback函数
                ->call(function () use ($smsSetting, $serverInfo) {
                    return $this->doSend($smsSetting, $serverInfo);
                });

            unset($smsSetting, $serverInfo);
        }
    }
    public function doSend($smsSetting, $serverInfo)
    {
        if (empty($this->params['single_phone'])) {
            return true;
        }
        $collection = mongodb2()->selectCollection('send_sms_log_' . $this->params['uid']);
        if (isset($this->params['ssl_id']) && !empty($this->params['ssl_id'])) {
            $postData['_id'] = $this->params['ssl_id'];
        } else {
            $postData['_id'] = createULId('SSL');
            $postData['st_id'] = $this->params['st_id'];
            $postData['ak_id'] = isset($serverInfo['ak_id']) ? $serverInfo['ak_id'] : '';
            $postData['uid'] = $this->params['uid'];
            $postData['ss_id'] = $this->params['ss_id'];
            $postData['params_json'] = $this->params['params_json'];
            $postData['send_content'] = '';
            $postData['send_content_tm'] = '';
            $postData['phone'] = (string)$this->params['single_phone'];
            $params = $this->params;
            unset($params['uid'], $params['single_phone']);
            $postData['params'] = json_encode($params, JSON_UNESCAPED_UNICODE);
            unset($params);
            $postData['title'] = '未知';
            $postData['send_result'] = false;
            $postData['send_error'] = '';
            $postData['platform'] = '';
            $postData['send_result_data'] = '';
            $postData['is_read'] = 0;
            $postData['read_time'] = 0;
            $postData['send_time'] = time();
            $postData['date'] = date('Ymd');
            $postData['hour'] = date('YmdH');
            $postData['only_hour'] = date('H') . ':00';
            $postData['hour_stamp'] = strtotime(date('Y-m-d H') . ':00:00');
            $postData['month'] = date('Ym');
            $postData['year'] = date('Y');
            // mongodb2()->send_sms_log->insertOne($postData);
            $collection->insertOne($postData);
            (new \App\Service\Common)->mongodbIndexCreate($collection, 'uid_send_time', ['uid' => 1, 'send_time' => -1]);
            (new \App\Service\Common)->mongodbIndexCreate($collection, 'uid_send_time_ss_id', ['uid' => 1, 'send_time' => -1, 'ss_id' => -1]);
        }
        if (empty($serverInfo)) {
            $collection->updateOne(['_id' => $postData['_id']], ['$set' => ['send_error' => '短信配置不存在或短信配置ID不正确']]);
            return true;
        }
        if ($serverInfo['status'] != 1) {
            $collection->updateOne(['_id' => $postData['_id']], ['$set' => ['send_error' => '短信配置未启用']]);
            return true;
        }
        $templateContent = $this->redisCache->getSmsTemplateRealTime($this->params['st_id']);
        if (empty($templateContent)) {
            $collection->updateOne(['_id' => $postData['_id']], ['$set' => ['send_error' => '短信模板不存在或短信模板ID不正确']]);
            return true;
        }
        $collection->updateOne(['_id' => $postData['_id']], ['$set' => ['title' => $templateContent['title']]]);
        $day_limit = $this->redisCache->sendLimit($this->params['ss_id'] . ':' . $this->params['single_phone'], 'day');
        if (!empty($day_limit) && !empty($smsSetting['day_limit']) && $day_limit > $smsSetting['day_limit']) {
            $collection->updateOne(['_id' => $postData['_id']], ['$set' => ['send_error' => '超过单个自然日内发送上限，发送失败']]);
            return true;
        }
        $hour_limit = $this->redisCache->sendLimit($this->params['ss_id'] . ':' . $this->params['single_phone'], 'hour');
        if (!empty($hour_limit) && !empty($smsSetting['hour_limit']) && $hour_limit > $smsSetting['hour_limit']) {
            $this->redisCache->sendLimitDec($this->params['ss_id'] . ':' . $this->params['single_phone'], 'day');
            $collection->updateOne(['_id' => $postData['_id']], ['$set' => ['send_error' => '超过每小时内发送上限，发送失败']]);
            return true;
        }
        $minute_limit = $this->redisCache->sendLimit($this->params['ss_id'] . ':' . $this->params['single_phone'], 'minute');
        if (!empty($minute_limit) && !empty($smsSetting['minute_limit']) && $minute_limit > $smsSetting['minute_limit']) {
            $this->redisCache->sendLimitDec($this->params['ss_id'] . ':' . $this->params['single_phone'], 'hour');
            $this->redisCache->sendLimitDec($this->params['ss_id'] . ':' . $this->params['single_phone'], 'day');
            $collection->updateOne(['_id' => $postData['_id']], ['$set' => ['send_error' => '超过每分钟内发送上限，发送失败']]);
            return true;
        }
        $result = [];
        $send_content = '';
        $send_content_tm = '';
        $send_sign = '';
        $params_json_array = (!empty($this->params['params_json'])) ? json_decode($this->params['params_json'], true) : [];
        if (!isset($serverInfo['platform_send_type']) || empty($serverInfo['platform_send_type'])) {
            $serverInfo['platform_send_type'] = 'text';
        }
        if (isset($templateContent['is_selected']) && $templateContent['is_selected'] == 'alone' && isset($templateContent['platform']) && !empty($templateContent['platform'])) {
            $serverInfo['platform'] = $templateContent['platform'];
            $akInfo = $this->redisCache->getAk($templateContent['ak_id'], $this->params['uid']);
            unset($akInfo['_id']);
            $serverInfo = array_merge($serverInfo, $akInfo);
            unset($akInfo);
            if (isset($templateContent['platform_send_type']) && !empty($templateContent['platform_send_type']) && $templateContent['platform_send_type'] != $serverInfo['platform_send_type']) {
                $serverInfo['platform_send_type'] = $templateContent['platform_send_type'];
            }
            if (isset($templateContent['aliyun_called_number']) && !empty($templateContent['aliyun_called_number']) && $templateContent['aliyun_called_number'] != $serverInfo['aliyun_called_number']) {
                $serverInfo['aliyun_called_number'] = $templateContent['aliyun_called_number'];
            }
        }
        switch ($serverInfo['platform']) {
            case 'aliyun':
                if ($serverInfo['platform_send_type'] == 'voice') {
                    $result = (new \App\Service\Sms\AliVoice)->sendRequest($this->params['single_phone'], $templateContent['aliyun_voice_code'], $this->params['params_json'], $serverInfo['aliyun_key_id'], $serverInfo['aliyun_key_secret'], $serverInfo['aliyun_called_number'], $postData['_id']);
                    $send_content = $templateContent['aliyun_voice'];
                    $send_content_tm = $templateContent['aliyun_voice'];
                    foreach ($params_json_array as $key => $vo) {
                        $send_content = str_replace('${' . $key . '}', "$vo", $send_content);
                        $send_content_tm = str_replace('${' . $key . '}', '***', $send_content_tm);
                    }
                } else {
                    $result = (new \App\Service\Sms\AliSms)->sendRequest($this->params['single_phone'], $templateContent['aliyun_tpl_code'], $this->params['params_json'], $serverInfo['aliyun_sign'], $serverInfo['aliyun_region'], $serverInfo['aliyun_key_id'], $serverInfo['aliyun_key_secret'], $this->params['client_ip']);
                    $send_content = $templateContent['aliyun_tpl'];
                    $send_content_tm = $templateContent['aliyun_tpl'];
                    $send_sign = $serverInfo['aliyun_sign'];
                    foreach ($params_json_array as $key => $vo) {
                        $send_content = str_replace('${' . $key . '}', "$vo", $send_content);
                        $send_content_tm = str_replace('${' . $key . '}', '***', $send_content_tm);
                    }
                }

                break;
            case 'tencent':
                $send_content = $templateContent['tencent_tpl'];
                $send_content_tm = $templateContent['tencent_tpl'];
                $params_json_array2 = [];
                foreach ($params_json_array as $key => $vo) {
                    $params_json_array2[] = "$vo";
                }
                foreach ($params_json_array2 as $key => $vo) {
                    $send_content = str_replace('{' . $key + 1 . '}', "$vo", $send_content);
                    $send_content_tm = str_replace('{' . $key + 1 . '}', '***', $send_content_tm);
                }
                $send_sign = $serverInfo['tenc_sign'];
                $result = (new \App\Service\Sms\TenSms)->sendRequest($this->params['single_phone'], $templateContent['tencent_tpl_code'], $params_json_array2, $serverInfo['tenc_sign'], $serverInfo['tenc_region'], $serverInfo['tenc_secret_key'], $serverInfo['tenc_secret_id'], $serverInfo['tenc_sdk_appid']);
                break;
            case 'huawei':
                $send_content = $templateContent['huawei_tpl'];
                $send_content_tm = $templateContent['huawei_tpl'];
                $params_json_array2 = [];
                foreach ($params_json_array as $key => $vo) {
                    $params_json_array2[] = "$vo";
                }
                foreach ($params_json_array2 as $key => $vo) {
                    $send_content = str_replace('${' . $key + 1 . '}', "$vo", $send_content);
                    $send_content_tm = str_replace('${' . $key + 1 . '}', '***', $send_content_tm);
                }
                $send_sign = $serverInfo['huawei_sign'];
                $result = (new \App\Service\Sms\HuaSms)->sendRequest($this->params['single_phone'], $templateContent['huawei_tpl_code'], $params_json_array2, $serverInfo['huawei_app_key'], $serverInfo['huawei_app_secret'], $serverInfo['huawei_app_url'], $serverInfo['huawei_sign_no'], $serverInfo['huawei_sign'], $postData['_id']);
                break;
            case 'jdcloud':
                $send_content = $templateContent['jdcloud_tpl'];
                $send_content_tm = $templateContent['jdcloud_tpl'];
                $params_json_array2 = [];
                foreach ($params_json_array as $key => $vo) {
                    $send_content = str_replace('${' . $key . '}', "$vo", $send_content);
                    $send_content_tm = str_replace('${' . $key . '}', '***', $send_content_tm);
                    $params_json_array2[] = "$vo";
                }
                $send_sign = $serverInfo['jdcloud_sign'];
                $result = (new \App\Service\Sms\JdSms)->sendRequest($this->params['single_phone'], $templateContent['jdcloud_tpl_code'], $params_json_array2, $serverInfo, $serverInfo['jdcloud_sign_id']);
                break;
            case 'smsbao':
                $send_content = $templateContent['smsbao_tpl'];
                $send_content_tm = $templateContent['smsbao_tpl'];
                foreach ($params_json_array as $key => $vo) {
                    $send_content = str_replace('{' . $key . '}', "$vo", $send_content);
                    $send_content_tm = str_replace('{' . $key . '}', '***', $send_content_tm);
                }
                $send_sign = $serverInfo['smsbao_sign'];
                $result = (new \App\Service\Sms\Smsbao)->sendRequest($this->params['single_phone'], $send_content, $serverInfo['smsbao_username'], $serverInfo['smsbao_password'], $serverInfo['smsbao_sign'], $postData['_id']);
                break;
            default:
                # code...
                break;
        }
        if (empty($result)) {
            $collection->updateOne(['_id' => $postData['_id']], ['$set' => ['send_error' => '未能获取到发送结果数据', 'send_content' => $send_content, 'platform_send_type' => $serverInfo['platform_send_type'], 'send_content_tm' => $send_content_tm,'send_sign'=> $send_sign, 'platform' => $serverInfo['platform']]]);
            return false;
        }
        $collection->updateOne(['_id' => $postData['_id']], ['$set' => ['send_error' => $result['send_error'], 'smsParam' => $result['smsParam'], 'send_result' => $result['send_result'], 'send_result_data' => $result['send_result_data'], 'send_sign' => $send_sign, 'send_content' => $send_content, 'send_content_tm' => $send_content_tm, 'platform_send_type' => $serverInfo['platform_send_type'], 'platform' => $serverInfo['platform']]]);
        unset($postData, $result, $serverInfo,$templateContent, $collection);
        return true;
    }
}
